#include <iostream>

#include <string>

#include <vector>

using namespace std;

// NOTE: 这里的 const 是修饰 sum, 引用类型或者指针类型 就需要声明为常量， 避免内部修改
// 函数泛型: typename 改为 class 也是可以的
template <typename T>
inline T const sum(T const &x, T const *y)
{
  // x = 100; 这里的 x 和 y 都是常量；
  return x + *y;
}

// NOTE: class 泛型

template <class T>
class Stack
{
  private:
    vector<T> data;
  public:
    void push(T const&);  // 入栈

    void pop();               // 出栈

    T top() const;            // 返回栈顶元素

    bool empty() const{       // 如果为空则返回真。
        return data.empty();
    }
};

template <class T>
void Stack<T>::push(T const &elem)
{
    // 追加传入元素的副本
    data.push_back(elem);
}

template <class T>
void Stack<T>::pop ()
{
    if (data.empty()) {
        // out_of_range 异常
        throw out_of_range("Stack<>::pop(): empty stack");
    }
    // 删除最后一个元素
    data.pop_back();
}

template <class T>
T Stack<T>::top () const
{
    if (data.empty()) {
      throw out_of_range("Stack<>::top(): empty stack");
    }
    // 返回最后一个元素的副本
    return data.back();
}

int main(int argc, char **argv)
{

  int x = 10;

  int y = 20;

  int z = sum(x, &y);

  cout << z << endl;

  double m = 4.2;
  double n = 3.3;
  double d = sum(m, &n);

  cout << d << endl;

  string s1 = "fuck";
  string s2 = " you";

  string s = sum(s1, &s2);

  cout << s << endl;

  Stack<int> intStack;

  intStack.push(1);

  return 0;
}
